package com.enbatis.dynamic.datasource.autoconfigure;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.enbatis.dynamic.datasource.autoconfigure.dynamic.DynamicTransactionAspect;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

/**
 * @author wwd
 * @date 2021-10-01 11:20
 */
@Configuration
@AutoConfigureAfter({DynamicDatasourceAutoConfiguration.class})
public class DynamicTxAutoConfiguration implements InitializingBean {

    @Autowired
    private Environment env;

    /**
     * JtaTransactionManager（）
     *
     * @return
     * @throws SystemException
     */
    @Bean(name = "userTransaction")
    @ConditionalOnProperty(
            name = {"jta.enabled"},
            havingValue = "true",
            matchIfMissing = false
    )
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(getDefaultTimeout());
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager")
    @ConditionalOnProperty(
            name = {"jta.enabled"},
            havingValue = "true",
            matchIfMissing = false
    )
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({"userTransaction", "atomikosTransactionManager"})
    @ConditionalOnProperty(
            name = {"jta.enabled"},
            havingValue = "true",
            matchIfMissing = false
    )
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();
        JtaTransactionManager manager = new JtaTransactionManager(userTransaction, atomikosTransactionManager());
        return manager;
    }


    public int getDefaultTimeout() {
        String property = env.getProperty("jta.timeout", "1800");
        if (!NumberUtils.isDigits(property)) {
            throw new RuntimeException("jta timeout must be int");
        }
        return Integer.parseInt(property);
    }


    @ConditionalOnProperty(
            name = {"jta.enabled"},
            havingValue = "true",
            matchIfMissing = false
    )
    @Bean
    public DynamicTransactionAspect dynamicTransactionAspect() {
        return new DynamicTransactionAspect();
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}
